package org.guegan.util.dircompare.main;

import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.guegan.util.dircompare.bean.DirBean;
import org.guegan.util.dircompare.bean.FileBean;
import org.guegan.util.dircompare.util.DirUtil;
import org.guegan.util.dircompare.util.FileToSignature;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

public class EstimationDirScanner extends DirScanner {
	private FileToSignature signer;
	private FileFilter filter;
	private static Log log = LogFactory.getLog(EstimationDirScanner.class);
	private File root;
	private Comparator<File> fileComparator;
	private int toScan = 0;
	private int dirsToScan = 0;
	
	public EstimationDirScanner() {
	}

	@Override
	protected void doExecute() throws Exception {
		toScan = 0;
		dirsToScan = 0;
		scanDir(root);
	}
	
	public int getToScan() {
		return toScan;
	}
	
	public int getDirsToScan() {
		return dirsToScan;
	}

	public void scanDir(File dir) {
		File[] contents = dir.listFiles(filter);
		//log.info(">>> " + dir + ": " + (contents != null ? contents.length : 0) + " elements(s)");
		DirBean parent = DirUtil.getInstance().getDir(dir, getSession());
		Map<String, FileBean> files = loadFiles(parent);
		int nbFiles = 0;
		if (contents != null) {
			if (fileComparator != null) {
				Arrays.sort(contents, fileComparator);
			}
			for (File file : contents) {
				if (file.isDirectory()) {
					scanDir(file);
				}
				else {
					log.debug("Examining " + file);
					nbFiles++;
					FileBean existing = files.get(file.getName());
					if (existing != null) {
						if (!existing.isPresent() || existing.getTime().getTime() != file.lastModified()) {
							toScan++;
						}
					}
					else {
						toScan++;
					}
					//signatures.append(existing.getSignature());
				}
			}
		}
		if (nbFiles != parent.getNbFiles()) {
			dirsToScan++;
		}
		if (!parent.isPresent()) {
			parent.setPresent(true);
			getSession().save(parent);
		}
		report(dir + " " + toScan + " file(s), " + dirsToScan + " dir(s) to scan", log);
	}
	
	@SuppressWarnings("unchecked")
	private Map<String, FileBean> loadFiles(DirBean parent) {
		Map<String, FileBean> ret = new HashMap<String, FileBean>(); 
		Criteria crit = getSession().createCriteria(FileBean.class);
		crit.add(Restrictions.eq("parent", parent));
		List<FileBean> existing = crit.list();
		for (FileBean file : existing) {
			ret.put(file.getName(), file);
		}
		return ret;
	}

	public FileToSignature getSigner() {
		return signer;
	}

	public void setSigner(FileToSignature signer) {
		this.signer = signer;
	}

	public FileFilter getFilter() {
		return filter;
	}

	public void setFilter(FileFilter filter) {
		this.filter = filter;
	}

	public void setRoot(File root) {
		this.root = root;
	}

	public File getRoot() {
		return root;
	}

	public Comparator<File> getFileComparator() {
		return fileComparator;
	}

	public void setFileComparator(Comparator<File> fileComparator) {
		this.fileComparator = fileComparator;
	}
	
}
